package com.aries.ui.helper.status;


import com.aries.ui.util.DrawableUtil;
import com.aries.ui.util.FindViewUtil;
import com.aries.ui.util.StatusBarUtil;
import com.aries.ui.view.viewgroup.ViewGroup;
import com.aries.ui.widget.ResourceTable;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.AbilityLifecycleCallbacks;
import ohos.aafwk.ability.AbilityPackage;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.element.Element;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.window.service.Window;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.app.ElementsCallback;
import ohos.global.configuration.Configuration;
import ohos.utils.PacMap;
import ohos.utils.PlainArray;

import java.lang.ref.WeakReference;
import java.util.Optional;

/**
 * @Author: AriesHoo on 2018/7/19 9:43
 * @E-Mail: AriesHoo@126.com
 * Function: 沉浸式状态栏控制帮助类
 * Description:
 * 1、2019-4-15 10:39:33 增加状态栏深色图标及文字颜色api {@link #setStatusBarLightMode(boolean)}
 * 2、2019-5-10 17:27:26 新增刘海屏适配
 * 3、2019-7-19 10:33:05 新增{@link #register()}监听生命周期自动进行资源回收
 */
public class StatusViewHelper {

    /**
     * 设置padding
     */
    public final static int TAG_SET_STATUS_CONTROL = 0x10000012;
    /**
     * 设置margin
     */
    public final static int TAG_SET_STATUS_CONTROL_MARGIN = 0x10000013;
    private static AbilityPackage instance;
    private String TAG = getClass().getSimpleName();
    private WeakReference<Ability> mActivity;
    /**
     * activity xml设置根布局
     */
    private ComponentContainer mContentView;
    private DirectionalLayout mLinearLayout;
    private DirectionalLayout mLayoutStatus;
    private Component mViewStatus;
    private boolean mLogEnable;
    private boolean mControlEnable;
    private boolean mTransEnable;
    private boolean mPlusStatusViewEnable;
    private Element mStatusViewDrawable;
    private Element mStatusLayoutDrawable;
    /**
     * 设置activity最底部View用于增加状态栏的padding
     */
    private Component mTopView;
    /**
     * 设置activity最顶部View用于是否增加导航栏margin
     */
    private boolean mTopViewMarginEnable;
    /**
     * 设置状态栏白底深色文字图标模式
     */
    private boolean mStatusBarLightMode;
    private boolean mIsInit;

    public String getTAG() {
        return TAG;
    }

    private StatusViewHelper(Ability activity, ComponentContainer root) {
        mActivity = new WeakReference(activity);
        mContentView = root;
    }

    public static StatusViewHelper with(Ability activity, ComponentContainer root) {
        if (activity == null) {
            throw new NullPointerException("null");
        }
        return new StatusViewHelper(activity, root);
    }

    public static void setAbilityPackage(AbilityPackage abilityPackage) {
        instance = abilityPackage;
    }

    /**
     * 注册Activity生命周期监听
     */
    private void register() {
        Ability activity = mActivity.get();
        if (activity == null) {
            return;
        }
        instance.registerCallbacks(new AbilityLifecycleCallbacks() {

            @Override
            public void onAbilityStart(Ability ability) {

            }

            @Override
            public void onAbilityActive(Ability ability) {

            }

            @Override
            public void onAbilityInactive(Ability ability) {

            }

            @Override
            public void onAbilityForeground(Ability ability) {

            }

            @Override
            public void onAbilityBackground(Ability ability) {

            }

            @Override
            public void onAbilityStop(Ability ability) {
                if (mActivity == null || activity == null) {
                    return;
                }
                Ability current = mActivity.get();
                //只移除当前Activity对象监听
                if (current == null || current != activity) {
                    return;
                }
                destroy();
            }

            @Override
            public void onAbilitySaveState(PacMap pacMap) {

            }
        }, new ElementsCallback() {
            @Override
            public void onMemoryLevel(int i) {

            }

            @Override
            public void onConfigurationUpdated(Configuration configuration) {

            }
        });
    }

    /**
     * 是否打印log
     *
     * @param logEnable  logEnable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setLogEnable(boolean logEnable) {
        mLogEnable = logEnable;
        return this;
    }

    /**
     * 设置是否控制虚拟导航栏
     *
     * @param controlEnable controlEnable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setControlEnable(boolean controlEnable) {
        mControlEnable = controlEnable;
        if (!controlEnable) {
            setPlusStatusViewEnable(true)
                    .setStatusLayoutDrawableColor(Color.BLACK.getValue())
                    .setStatusViewColor(Color.BLACK.getValue());
        }
        return this;
    }

    /**
     * 设置是否全透明
     *
     * @param transEnable  transEnable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setTransEnable(boolean transEnable) {
        this.mTransEnable = transEnable;
        if (mContentView != null && mContentView.getBackgroundElement() != null) {
            setStatusLayoutDrawable(DrawableUtil.getNewDrawable(mContentView.getBackgroundElement()));
        } else {
            setStatusLayoutColor(Color.WHITE.getValue());
        }
        return setStatusViewColor(transEnable ? Color.TRANSPARENT.getValue() : Color.argb(102, 0, 0, 0));
    }

    /**
     * 是否设置假的导航栏--用于沉浸遮挡
     *
     * @param plusStatusViewEnable   plusStatusViewEnable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setPlusStatusViewEnable(boolean plusStatusViewEnable) {
        this.mPlusStatusViewEnable = plusStatusViewEnable;
        if (mPlusStatusViewEnable) {
            setTransEnable(true);
        }
        return this;
    }

    /**
     * 设置状态栏白底深色文字图标模式
     *
     * @param statusBarLightMode  statusBarLightMode
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusBarLightMode(boolean statusBarLightMode) {
        this.mStatusBarLightMode = statusBarLightMode;
        return this;
    }

    /**
     * 设置 StatusView背景颜色
     *
     * @param StatusViewColor ColorInt
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusViewColor(int StatusViewColor) {
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(RgbColor.fromArgbInt(StatusViewColor)));
        return setStatusViewDrawable(element);
    }

    /**
     * 设置假StatusView背景资源
     *
     * @param drawable  drawable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusViewDrawable(Element drawable) {
        this.mStatusViewDrawable = drawable;
        return this;
    }

    /**
     * 设置假StatusView父ViewGroup背景颜色
     *
     * @param StatusLayoutColor ColorInt
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusLayoutColor(int StatusLayoutColor) {
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(RgbColor.fromArgbInt(StatusLayoutColor)));
        return setStatusLayoutDrawable(element);
    }

    /**
     * 设置假StatusView父ViewGroup背景颜色
     *
     * @param colorInt  colorInt
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusLayoutDrawableColor(int colorInt) {
        ShapeElement element = new ShapeElement();
        element.setRgbColor(new RgbColor(RgbColor.fromArgbInt(colorInt)));
        return setStatusLayoutDrawable(element);
    }

    /**
     * 设置假StatusView父ViewGroup背景资源
     *
     * @param StatusLayoutDrawable  StatusLayoutDrawable
     * @return  StatusViewHelper
     */
    public StatusViewHelper setStatusLayoutDrawable(Element StatusLayoutDrawable) {
        this.mStatusLayoutDrawable = StatusLayoutDrawable;
        return this;
    }

    /**
     * 设置最顶部--虚拟状态栏上边的View
     *
     * @param view  view
     * @param enable 是否设置Margin
     * @return  StatusViewHelper
     */
    public StatusViewHelper setTopView(Component view, boolean enable) {
        if (mTopView != null) {
            resetStatusView(mTopView);
        }
        mTopView = view;
        mTopViewMarginEnable = enable;
        return this;
    }

    public StatusViewHelper setTopView(Component view) {
        return setTopView(view, false);
    }

    /**
     * 快速设置状态栏白色样式、注意和其它方法调用顺序
     *
     * @return StatusViewHelper 对象
     */
    public StatusViewHelper setWhiteStyle() {
        return setControlEnable(true)
                .setTransEnable(true)
                .setPlusStatusViewEnable(true)
                .setTopView(getTopView(mContentView))
                .setStatusBarLightMode(StatusBarUtil.isSupportStatusBarFontChange())
                .setStatusViewColor(Color.argb(StatusBarUtil.isSupportStatusBarFontChange() ? 0 : 102, 0, 0, 0))
                .setStatusLayoutDrawableColor(Color.WHITE.getValue());
    }

    /**
     * 快速设置状态栏黑色样式、注意和其它方法调用顺序
     *
     * @return StatusViewHelper 对象
     */
    public StatusViewHelper setBlackStyle() {
        return setControlEnable(true)
                .setTransEnable(true)
                .setPlusStatusViewEnable(true)
                .setTopView(getTopView(mContentView))
                .setStatusBarLightMode(false)
                .setStatusViewColor(Color.BLACK.getValue())
                .setStatusLayoutDrawableColor(Color.BLACK.getValue());
    }

    /**
     * 获取顶部View
     *
     * @param target 目标View
     * @return 返回顶部View
     */
    private Component getTopView(Component target) {
        if (target != null && target instanceof ViewGroup) {
            ComponentContainer group = (ComponentContainer) target;
            if (group.getChildCount() > 0) {
                target = ((ComponentContainer) target).getComponentAt(0);
            }
        }
        return target;
    }

    /**
     * 开始设置StatusView相应效果
     * @param root  root
     * @exception NullPointerException 空指针异常
     */
    public void init(ComponentContainer root) {
        Ability activity = mActivity.get();
        if (activity == null || activity.isTerminating()) {
            throw new NullPointerException("not exist");
        }
        if (!mIsInit) {
            mIsInit = true;
            register();
        }
        setControlEnable(mControlEnable);
        resetStatusView(mTopView);
        if (mStatusBarLightMode) {
            StatusBarUtil.setStatusBarLightMode(activity);
        } else {
            StatusBarUtil.setStatusBarDarkMode(activity);
        }

        final Window window = activity.getWindow();
        //透明状态栏
        window.addFlags(WindowManager.LayoutConfig.MARK_TRANSLUCENT_STATUS);
        int now = root.getVisibility();
        int temp = (now & WindowManager.LayoutConfig.MARK_FULL_SCREEN) == WindowManager.LayoutConfig.MARK_FULL_SCREEN ? now ^ WindowManager.LayoutConfig.MARK_FULL_SCREEN : now;
        int systemUi = mControlEnable ?
                now | WindowManager.LayoutConfig.MARK_FULL_SCREEN : temp;
        root.setVisibility(systemUi);
        if (mControlEnable) {
            window.addFlags(WindowManager.LayoutConfig.MARK_DRAWS_SYSTEM_BAR_BACKGROUNDS);
        }
        window.setStatusBarColor(!mControlEnable ? Color.BLACK.getValue() : Color.TRANSPARENT.getValue());
        if (!mTransEnable) {
            window.setStatusBarColor(Color.argb(mControlEnable ? 102 : 0, 0, 0, 0));
        }
        StatusBarUtil.fitsNotchScreen(window, mControlEnable);

        addStatusBar(root);
        setStatusView();
        setTopView();
    }

    /**
     * 添加假状态栏
     *
     * @param root  root
     */
    private void addStatusBar(ComponentContainer root) {
        if (!isSupportStatusBarControl()) {
            return;
        }
        if (mLinearLayout == null) {
            mLinearLayout = FindViewUtil.getTargetView(root, DirectionalLayout.class);
        }
        if (mLinearLayout != null && mPlusStatusViewEnable) {
            final DirectionalLayout linearLayout = mLinearLayout;
            Context mContext = root.getContext();
            //创建假的StatusView包裹ViewGroup用于设置背景与mContentView一致
            mLayoutStatus = (DirectionalLayout) linearLayout.findComponentById(ResourceTable.Integer_fake_status_layout);

            if (mLayoutStatus == null) {
                mLayoutStatus = new DirectionalLayout(mContext);
                mLayoutStatus.setId(ResourceTable.Integer_fake_status_layout);
                //创建假的StatusView
                mViewStatus = new Component(mContext);
                ComponentContainer.LayoutConfig params = new ComponentContainer.LayoutConfig(
                        ComponentContainer.LayoutConfig.MATCH_PARENT, 72);
                mViewStatus.setId(ResourceTable.Integer_fake_status_view);
                mLayoutStatus.addComponent(mViewStatus, params);
                linearLayout.addComponent(mLayoutStatus, 0, params);
            } else {
                mViewStatus = mLayoutStatus.findComponentById(ResourceTable.Integer_fake_status_view);
            }
        }
    }

    /**
     * 设置假状态栏样式
     */
    private void setStatusView() {
        if (mLayoutStatus != null) {
            mLayoutStatus.setBackground(mStatusLayoutDrawable);
            mViewStatus.setBackground(mStatusViewDrawable);
            ComponentContainer.LayoutConfig params = mLayoutStatus.getLayoutConfig();
            if (params != null) {
                params.height = isSupportStatusBarControl() && mPlusStatusViewEnable ? getNeedTop(mLayoutStatus) : 0;
            }
        }
    }

    private int getNeedTop(Component view) {
        int status = StatusBarUtil.getStatusBarHeight(view.getContext());
//        int safe = NotchUtil.getSafeInsetTop(view);
        return isSupportStatusBarControl() ? status : 0;
    }

    /**
     * 设置顶部状态栏效果-padding或margin
     */
    private void setTopView() {
        if (mTopView == null || mPlusStatusViewEnable || !mControlEnable) {
            return;
        }
        mTopView.setLayoutRefreshedListener(component -> {
            ComponentContainer.LayoutConfig params = mTopView.getLayoutConfig();
            //是否处理过topView
            Object control = checkTag(mTopView, TAG_SET_STATUS_CONTROL);
            boolean isSet = control instanceof Boolean ? ((Boolean) control) : false;
            if (mTopViewMarginEnable) {
                control = checkTag(mTopView, TAG_SET_STATUS_CONTROL_MARGIN);
                isSet = control instanceof Boolean ? ((Boolean) control) : false;
                if (params != null) {
                    int topMargin = params.getMarginTop() + (isSet ? 0 : getNeedTop(mTopView));
                    params.setMarginTop(topMargin);
                    mTopView.setLayoutConfig(params);
                }
                addTag(mTopView, TAG_SET_STATUS_CONTROL_MARGIN, true);
            } else {
                //默认
                if (params != null && params.height >= 0) {
                    params.height += isSet ? 0 : getNeedTop(mTopView);
                }
                mTopView.setPadding(
                        mTopView.getPaddingLeft(),
                        mTopView.getPaddingTop() + (isSet ? 0 : getNeedTop(mTopView)),
                        mTopView.getPaddingRight(),
                        mTopView.getPaddingBottom());
                addTag(mTopView, TAG_SET_STATUS_CONTROL, true);
            }
        });
    }

    protected boolean isSupportStatusBarControl() {
        return true;
    }

    /**
     * 重置状态
     * @param topView  topView
     */
    private void resetStatusView(Component topView) {
        if (topView == null) {
            return;
        }
        Object control = checkTag(topView, TAG_SET_STATUS_CONTROL);
        boolean isSet = control instanceof Boolean ? ((Boolean) control) : false;
        ComponentContainer.LayoutConfig params = topView.getLayoutConfig();
        //设置了paddingTop
        if (isSet) {
            //默认
            if (params != null && params.height >= 0) {
                params.height -= getNeedTop(topView);
            }
            topView.setPadding(
                    topView.getPaddingLeft(),
                    topView.getPaddingTop() - getNeedTop(topView),
                    topView.getPaddingRight(),
                    topView.getPaddingBottom());
            addTag(topView, TAG_SET_STATUS_CONTROL, false);
        }
        control = checkTag(topView, TAG_SET_STATUS_CONTROL_MARGIN);
        isSet = control instanceof Boolean ? ((Boolean) control) : false;
        if (isSet) {
            if (params != null) {
                int topMargin = params.getMarginTop() - getNeedTop(topView);
                params.setMarginTop(topMargin);
            }
            addTag(topView, TAG_SET_STATUS_CONTROL_MARGIN, false);
        }
    }

    private Object checkTag(Component target, int tagValue) {
        Object tag = target.getTag();
        PlainArray<Boolean> array = (tag != null) ? (PlainArray) tag : null;
        Object control;
        if (array != null) {
            Optional<Boolean> optional = array.get(tagValue);
            control = optional.orElse(null);
        } else {
            control = null;
        }
        return control;
    }

    private void addTag(Component target, int tagValue, boolean value) {
        Object tag = target.getTag();
        PlainArray<Boolean> array = (tag != null) ? (PlainArray) tag : new PlainArray<>();
        array.append(tagValue, value);
        target.setTag(array);
    }

    public void destroy() {
        if (mLinearLayout != null && mLayoutStatus != null) {
            mLinearLayout.removeComponent(mLayoutStatus);
        }
        resetStatusView(mTopView);
        mActivity = null;
        mContentView = null;
        mViewStatus = null;
        mStatusViewDrawable = null;
        mStatusLayoutDrawable = null;
        mLayoutStatus = null;
        mTopView = null;
    }
}
